﻿using AspNetCoreRateLimit;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NLog;
using ZR.ServiceCore.Model;
using ZR.ServiceCore.Services.IService;
using RateLimitRule = AspNetCoreRateLimit.RateLimitRule;

namespace ZR.ServiceCore.Middleware;

public class CustomIpRateLimitMiddleware : IpRateLimitMiddleware
{
    private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

    private readonly IIpRateLimitLogService _ipRateLimitLogService;
        
    public CustomIpRateLimitMiddleware(RequestDelegate next, IProcessingStrategy processingStrategy, 
        IOptions<IpRateLimitOptions> options, IIpPolicyStore policyStore, IRateLimitConfiguration config, 
        ILogger<IpRateLimitMiddleware> logger, IIpRateLimitLogService ipRateLimitLogService) : base(next, processingStrategy, options, policyStore, config, logger)
    {
        _ipRateLimitLogService = ipRateLimitLogService;
    }

    protected override void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, 
        RateLimitCounter counter, RateLimitRule rule)
    {
        // base.LogBlockedRequest(httpContext, identity, counter, rule);
        var nowDate = DateTime.Now;
        var ipRateLimitLog = new IpRateLimitLog
        {
            HttpVerb = identity.HttpVerb,
            Path = identity.Path,
            ClientIp = identity.ClientIp,
            Limit = rule.Limit,
            Period = rule.Period,
            Exceeded = counter.Count - rule.Limit,
            Endpoint = rule.Endpoint,
            CreateTime = nowDate
        };
        var logStr = $"请求 {ipRateLimitLog.HttpVerb}:{ipRateLimitLog.Path} 来自 IP {ipRateLimitLog.ClientIp} 已被阻止, " +
                     $"配额 {ipRateLimitLog.Limit}/{ipRateLimitLog.Period} 超出次数 {ipRateLimitLog.Exceeded}. " +
                     $"被规则 {ipRateLimitLog.Endpoint} 阻止. 时间: {ipRateLimitLog.CreateTime}";
        Logger.Info(logStr);
        _ipRateLimitLogService.InsertIpRateLimitLogAsync(ipRateLimitLog);
    }
}